﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoolanElement;
using BoolanSlide.BooCommon;
using Windows.Storage;
using Windows.Storage.Streams;

namespace BoolanElement.Storage

{
    public class BPTFileBlock
    {
        private const string EncryptionMode = "EncryptionMode";
        private const string DefaultMode = "DefaultType";
        private long HeaderSize;
        public String FileName;
        public String GroupName;
        public String Type;
        public long BlockSize;
        public StorageFile MainFile;
        public IBuffer Data;
        public byte[] ByteData;
        public BPTFileBlock()
        {
            HeaderSize = 0;
            FileName = "DefaultName";
            GroupName = "DefaultGroup";
            Type = DefaultMode;
            BlockSize = 0;
        }

        public void CaculateHeader()
        {
            String HeaderOutput=FileName+","+GroupName+","+Type;
            HeaderSize = HeaderOutput.Length;
            HeaderSize += 16;
        }

        public void SetHeader(String serialString)
        {
            String[] items=serialString.Split(",".ToCharArray());
            FileName = items[0];
            GroupName = items[1];
            Type = items[2];
        }

        public async Task<bool> WriteToArchive(DataWriter writer)
        {
            CaculateHeader();
            writer.WriteInt64((long)HeaderSize);
            writer.WriteString(FileName+","+GroupName+","+Type);

            if (Type == EncryptionMode)
            {
                string data = ZipTool.Zip(ByteData);
                BlockSize = HeaderSize + data.Length;
                writer.WriteInt64(BlockSize);
                writer.WriteString(data);
            }
            else if(Type==DefaultMode)
            {
                BlockSize = HeaderSize + ByteData.Length;
                writer.WriteInt64(BlockSize);
                writer.WriteBytes(ByteData);
            }
      

            return true;
        }

        public static async Task<BPTFileBlock> FromFileAsync(StorageFile file)
        {
            BPTFileBlock block = null;
            using ( IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
            {
                using (DataReader reader = new DataReader(stream.GetInputStreamAt(0)))
                {
                    await reader.LoadAsync((uint)stream.Size);
                    block = new BPTFileBlock();
                    block.FileName = file.Name;
                    block.ByteData = new byte[(uint)stream.Size];
                    reader.ReadBytes(block.ByteData);
                }
            }
            return block;
        }

        public async void Load(string content)
        {
            this.FileName = "xmlfile";
            this.ByteData = System.Text.Encoding.UTF8.GetBytes(content);
        }

        public static async Task<BPTFileBlock> FromArchiveAsync(DataReader archiveReader)
        {
            if (archiveReader.UnconsumedBufferLength <= 0)
                return null;
            BPTFileBlock block = new BPTFileBlock();
            long headerSize = archiveReader.ReadInt64();
            block.HeaderSize=headerSize;
            String headInfo=archiveReader.ReadString((uint)headerSize-16);
            block.SetHeader(headInfo);
            block.BlockSize = archiveReader.ReadInt64();

            if (block.Type == DefaultMode)
            {
                block.ByteData = new byte[(uint)block.BlockSize - (uint)block.HeaderSize];
                archiveReader.ReadBytes(block.ByteData);
            }
            else if (block.Type == EncryptionMode)
            {
                string data = archiveReader.ReadString((uint)block.BlockSize - (uint)block.HeaderSize);
                block.ByteData = ZipTool.UnZip(data);
            }
            
            return block;
        }

        /// <summary>
        /// 将块保存为文件，暂不使用
        /// </summary>
        /// <param name="folderInfomation"></param>
        /// <returns></returns>
        public async Task<bool> SaveToFile(StorageFile file)
        {
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                stream.Size = 0;
                using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
                {
                    writer.WriteBytes(ByteData);
                    await writer.StoreAsync();
                    await writer.FlushAsync();
                }
            }
            return true;
        }
    }
}
